package gesturetracking;

import com.primesense.NITE.*;
import java.awt.Component;
import java.awt.GridLayout;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import nite.gestures.*;
import nite.gestures.AbstractGesture.PointUpdateObserver;
import nite.gestures.AbstractGesture.PrimaryPointUpdateObserver;
import org.OpenNI.*;
/**
 *
 * @author xvanek9
 */
public class GestureTracking extends Component {
//
//    String calibPose = null;
//    
//    private boolean drawBackground = true;
//    private boolean drawPixels = true;
//    private boolean drawSkeleton = true;
//    private boolean printID = true;
//    private boolean printState = true;
    
    private static final String SAMPLE_XML_FILE = "Y:/SamplesConfig.xml";
    
    OutArg<ScriptNode> scriptNode;
    Context context;
    DepthGenerator depthGen;
    DepthMetaData depthMD;
    UserGenerator userGen;
    ImageGenerator imageGen;
    SkeletonCapability skeletonCap;
    PoseDetectionCapability poseDetectionCap;
    CursorPanel cp;
    GestureGenerator gestGen;
    CameraPanel panel;
    SkeletonJoint [] availBones;
    private SessionManager sessMan;
    private boolean isRunning=true;
    
    HashMap<Integer, HashMap<SkeletonJoint, SkeletonJointPosition>> joints;
    
    private void configOpenNI(){
        try {
            HandsGenerator handsGen = HandsGenerator.create(context);
            handsGen.SetSmoothing(0.1f);
            setHandEvents(handsGen);
            
            depthGen = DepthGenerator.create(context);
            depthMD = depthGen.getMetaData();
            userGen = UserGenerator.create(context);
            skeletonCap = userGen.getSkeletonCapability();
            poseDetectionCap = userGen.getPoseDetectionCapability();
            System.out.println(depthGen.getDeviceMaxDepth());
            imageGen = ImageGenerator.create(context);
            System.out.println(imageGen.getMetaData().getFPS());
            
            gestGen = GestureGenerator.create(context);
            depthGen = DepthGenerator.create(context);
            
            JFrame frame = new JFrame("Kinect view");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(1300, 520);

            GridLayout g1 = new GridLayout();
            frame.getContentPane().setLayout(g1);
            
            panel = new CameraPanel();
            panel.setVisible(true);
            
            cp = new CursorPanel();
            cp.setVisible(true);
            
            frame.getContentPane().add(panel);
            frame.getContentPane().add(cp);
            frame.setVisible(true);
            
            context.startGeneratingAll();
            
        } catch (GeneralException ex) {
            
        }
    }
    
//    public void updateData(){
//        try {
//            context.waitAnyUpdateAll();
//            panel.update(imageGen);
//        } catch (StatusException ex) {
//            Logger.getLogger(GestureTracking.class.getName()).log(Level.SEVERE, null, ex);
//        }
//    }
    
    private void configNite(){
        try {
            sessMan = new SessionManager(context, "Wave", "RaiseHand");
            PointControl pointCtrl = initPointControl();
            WaveGesture wave = new WaveGesture();
            WaveDetector wd = wave.init();
            SwipeGesture swipe = new SwipeGesture();
            SwipeDetector sd = swipe.init();
            //prozkoumat steady detector
            SteadyGesture steady = new SteadyGesture();
            SteadyDetector std = steady.init(2000);
            PushGesture push = new PushGesture();
            PushDetector pd = push.init();
            CircleGesture circle = new CircleGesture();
            CircleDetector cd = circle.init();
            
            cp.getObservers().add(wave.getObs());
            //nejde nevim proc
            //cp.getObservers().add(swipe.getObs());
            cp.getObservers().add(steady.getObs());
            cp.getObservers().add(push.getObs());
            cp.getObservers().add(circle.getObs());

            sessMan.addListener(pointCtrl);
            sessMan.addListener(wd);
            sessMan.addListener(sd);
            sessMan.addListener(pd);
            sessMan.addListener(cd);
            sessMan.addListener(std);
            
            //...chapter 7
            
        } catch (GeneralException ex) {
            
        }
    }
    
    public GestureTracking() {
        try {
//        context = new Context();
//        License licence = new License("PrimeSense", "0KOIk2JeIBYClPWVnMoRKn5cdY4=");
//        context.addLicense(licence);
        scriptNode = new OutArg<ScriptNode>();
        context = Context.createFromXmlFile(SAMPLE_XML_FILE, scriptNode);
            
        configOpenNI();
        configNite();

        while (isRunning){
            context.waitAnyUpdateAll();
            panel.update(imageGen);
            cp.updateLabel();
            sessMan.update(context);
        }
        
        } catch (GeneralException ex) {
            Logger.getLogger(GestureTracking.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void setHandEvents(HandsGenerator handsG){
        try {
            handsG.getHandCreateEvent().addObserver(new IObserver<ActiveHandEventArgs>() {

                @Override
                public void update(IObservable<ActiveHandEventArgs> io, ActiveHandEventArgs args) {
                    int id = args.getId();
                    Point3D pt = args.getPosition();
                    float time = args.getTime();
                    System.out.println(pt);
                }
            });
            handsG.getHandDestroyEvent().addObserver(new IObserver<InactiveHandEventArgs>() {

                @Override
                public void update(IObservable<InactiveHandEventArgs> io, InactiveHandEventArgs args) {
                    System.out.println("Hand is gone");
                }
            });
        } catch (StatusException ex) {
            Logger.getLogger(GestureTracking.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   
    private PointControl initPointControl(){
        PointControl pointCtrl = null;
        try {
            pointCtrl = new PointControl();
            
            pointCtrl.getPointCreateEvent().addObserver(new IObserver<HandEventArgs>(){

                @Override
                public void update(IObservable<HandEventArgs> io, HandEventArgs args) {
                   System.out.println(args.getHand());
                }
            });
            
            pointCtrl.getPointUpdateEvent().addObserver(new IObserver<HandEventArgs>(){

                @Override
                public void update(IObservable<HandEventArgs> io, HandEventArgs args) {
                    HandPointContext handContext = args.getHand();
                }
            });
            
        } catch (GeneralException ex) {
            Logger.getLogger(GestureTracking.class.getName()).log(Level.SEVERE, null, ex);
        }
        return pointCtrl;
    }

}
